#ifndef _RINGIO_H_
#define _RINGIO_H_

#include <stdint.h>
#include "frm_struct_def.h"

typedef ERRCODE (*RingIoHandle)(const uint8_t* buff, uint32_t len);

class kzlink {
public:
    kzlink() {}
    /* init io */
    void InitFrmHead(const char* head) {m_frmHead = head; }
    void InitRingBufRx(uint8_t* rxbuff, uint32_t rxDepth);
    void InitRingBufTx(uint8_t* txbuff, uint32_t txDepth);
    void RegTxHandle(RingIoHandle txFunc) { m_txFunc = txFunc; }
    void RegExe(uint32_t pkgType, uint32_t size, RingIoHandle exe);
    /* called upon rx dma event */
    void RecvHandle(uint32_t incomingBytes) { m_inComingBytesCnt = incomingBytes; }
    ERRCODE SendHandle(pkgType type, const void* src, uint32_t len);
    /* scanning */
    void ConsumeRx();
    /* DFX */
    void Dump();
private:
    void PrintUsageBar();
    void FlushRx();
    RingIoHandle m_txFunc = nullptr;
    /* protocol decode function */
    ERRCODE ValidPkg(const uint8_t* data, size_t len) const;
    pkgType GetType(const uint8_t* data, size_t len) const;
    const uint8_t* GetPayload(const uint8_t* data, size_t len) const;
    uint32_t GetPayloadLen(const uint8_t* data, size_t len) const;
    ERRCODE EchoAck(ERRCODE errCode, uint32_t recvCmdID, const uint8_t* data, size_t len);

private:
    const char* m_frmHead = nullptr;
    uint8_t* m_rxbuff = nullptr;
    uint8_t* m_txbuff = nullptr;
    uint32_t m_rxDepth = 1024;
    uint32_t m_txDepth = 1024;
    uint8_t* m_head = nullptr;
    uint8_t* m_tail = nullptr;
    uint8_t* m_rxbuffMirro = nullptr;
    CioSta m_sta;
    uint32_t m_pkgLen[FRM_TYPE_MAX] = {0};
    RingIoHandle m_exe[FRM_TYPE_MAX] = {nullptr};
    uint32_t m_inComingBytesCnt = 0;
    uint32_t m_rxRecvedTotal = 0;
    uint32_t m_rxRecvedValid = 0;
};

#endif // _RINGIO_H_